import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.stage.Stage;

import java.util.HashSet;
import java.util.Set;

public class TreeViewSingleExpandDemo extends Application {

    @Override
    public void start(Stage primaryStage) {
        TreeItem<String> root = createSampleTree();
        TreeView<String> treeView = new TreeView<>(root);
        root.setExpanded(true); // 默认展开根节点

        // 为每个节点添加监听器
        addExpandListener(root, treeView);

        Scene scene = new Scene(treeView, 400, 300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("TreeView 单展开链示例");
        primaryStage.show();
    }

    private void addExpandListener(TreeItem<String> item, TreeView<String> treeView) {
        item.expandedProperty().addListener((obs, wasExpanded, isNowExpanded) -> {
            if (isNowExpanded) {
                // 获取当前节点的所有祖先
                Set<TreeItem<String>> ancestorChain = new HashSet<>();
                TreeItem<String> current = item;
                while (current != null) {
                    ancestorChain.add(current);
                    current = current.getParent();
                }

                // 收起所有不在祖先链的已展开节点
                collapseOthers(treeView.getRoot(), ancestorChain);
            }
        });

        // 递归添加到所有子节点
        for (TreeItem<String> child : item.getChildren()) {
            addExpandListener(child, treeView);
        }
    }

    private void collapseOthers(TreeItem<?> node, Set<TreeItem<String>> keepExpanded) {
        if (node != null) {
            for (TreeItem<?> child : node.getChildren()) {
                collapseOthers(child, keepExpanded);
            }

            if (!keepExpanded.contains(node)) {
                node.setExpanded(false);
            }
        }
    }

    private TreeItem<String> createSampleTree() {
        TreeItem<String> root = new TreeItem<>("根节点");

        TreeItem<String> a = new TreeItem<>("A");
        TreeItem<String> a1 = new TreeItem<>("A1");
        TreeItem<String> a2 = new TreeItem<>("A2");
        a.getChildren().addAll(a1, a2);

        TreeItem<String> b = new TreeItem<>("B");
        TreeItem<String> b1 = new TreeItem<>("B1");
        TreeItem<String> b2 = new TreeItem<>("B2");
        b.getChildren().addAll(b1, b2);

        root.getChildren().addAll(a, b);

        return root;
    }

    public static void main(String[] args) {
        launch(args);
    }
}